
public class GameLogic implements IGameLogic {
	private State s;
	private final static int cutoffDepth = 40;

	public void initializeGame(int cols, int rows, int playerID){
		s = new State(cols, rows, playerID);
	}

	public int gameFinished() {
		return s.terminateTest();
	}

	public void insertCoin(int col, int playerID) {
		s.insertCoin(col, playerID);
	}

	public int decideNextMove() {
		//		System.out.println("player ID: " + s.playerID);
		//		int iPick = (int) (Math.random() * s.openCols.size());
		//		return s.openCols.get(iPick);
		Integer alpha = Integer.MIN_VALUE, beta = Integer.MAX_VALUE;
		maxValue(s, "", cutoffDepth, alpha, beta );
		//		System.out.println("minimax result: " + result.value + "   next: " + result.action);
		//		System.out.println("-----------------------------------------------");
		//		System.out.println(s.playerID);
		return nextMove;
	}

	public static int minimaxAdapter(int winner, State s, int depth) {
		if (winner == 0) {	//   game not over
			return 0;
		} else if (winner == s.ID) {     // computer player won
			return 10000 + depth;
		} else if (winner != s.ID ) {    // computer player lost
			return -10000 + (cutoffDepth - depth);  
		} else {
			return -100 + (cutoffDepth - depth); 	// Tie
		}
	}

	private static int nextMove = -1;
	public static int maxValue(State s, String space, int depth, Integer alpha, Integer beta) {
		int outcome = minimaxAdapter(s.terminateTest(), s, depth);
		if (outcome != 0) {
//			System.out.println("outcome: " + outcome);
			return outcome;
		}
//		if (depth == 0) {
//			return 0;
//		}
		int v = Integer.MIN_VALUE;
		int bestMove = -1;
		//		System.out.println(space + "max");
		//		int[] vals = new int[actions.size()];
		//		int c = 0;
		for (Integer openCol : s.openCols) {
			State nextState = new State(s);
			nextState.insertCoin(openCol, s.playerID);
			nextState.switchTurn();
			//			actions.get(i).print(space);
			int val = minValue(nextState, space + " ", depth - 1, alpha, beta);
			
			if (val > v) {
				bestMove = openCol;
				if (val > 0) {
					if (depth == cutoffDepth) {
						nextMove = bestMove;
					}
					return val;
				}
				v = val;
			}
			
			if (val >= beta) {
				if (depth == cutoffDepth) {
					nextMove = bestMove;
				}
				return val;
			}
			alpha = Math.max(val, alpha);
			//			vals[c++] = val;
			
		}
		//		System.out.print(space);
		//		for (int i : vals) {
		//			System.out.print(i + ", ");
		//		}
		//		System.out.println("\n");
		if (depth == cutoffDepth) {
			nextMove = bestMove;
		}
		return v; 
	}

	public static int minValue(State s, String space, int depth, Integer alpha, Integer beta) {
		int outcome = minimaxAdapter(s.terminateTest(), s, depth);
		//		System.out.println(space + "outcome: " + outcome + "\n");
		if (outcome != 0)
			return outcome;
		int v = Integer.MAX_VALUE;
		for (Integer nextCol : s.openCols) {
			State nextState = new State(s);
			nextState.insertCoin(nextCol, s.playerID);
			nextState.switchTurn();
			//			actions.get(i).print(space);
			
			v = Math.min(v, maxValue(nextState, space + " ", depth - 1, alpha, beta));
			if (v <= alpha) {
				if (depth == cutoffDepth) {
					nextMove = nextCol;
				}
				return v;
			}
			beta = Math.max(v, beta);
		}
		return v;  
	}

	public static void main(String[] args) {
		GameLogic g = new GameLogic();
		g.initializeGame(4, 3, 1);
		g.s.printAll();
		g.s.insertCoin(1, 2);
		
		Integer alpha = Integer.MIN_VALUE, beta = Integer.MAX_VALUE;
		System.out.println(maxValue(g.s, "", cutoffDepth, alpha, beta ));
		
	}

}
